using System.Linq;
using UniversalAdmin.Application.Common;
using UniversalAdmin.Application.Dtos.Role;
using UniversalAdmin.Application.Dtos;
using UniversalAdmin.Application.Dtos.Menu;
using UniversalAdmin.Application.Services.Interfaces;
using UniversalAdmin.Domain.Entities.App;
using UniversalAdmin.Domain.Repositories;
using UniversalAdmin.Infrastructure.Data.Contexts;
using Microsoft.EntityFrameworkCore;
namespace UniversalAdmin.Application.Services.Implementations;


public class RoleService : IRoleService
{
    private readonly IRepositories<Role> _roleRepository;
    private readonly IRepositories<Menu> _menuRepository;
    private readonly AdminDbContext _dbContext;

    public RoleService(IRepositories<Role> roleRepository, IRepositories<Menu> menuRepository, AdminDbContext dbContext)
    {
        _roleRepository = roleRepository;
        _menuRepository = menuRepository;
        _dbContext = dbContext;
    }

    /// <summary>
    /// 为角色分配菜单权限
    /// </summary>
    /// <param name="roleId">角色ID</param>
    /// <param name="menuId">菜单ID</param>
    /// <returns>操作结果</returns>
    public async Task<dynamic> AssignMenuToRoleAsync(Guid roleId, Guid menuId)
    {
        // 检查角色是否已经拥有该菜单权限 - 使用Table查询来检查关系
        var existingRelation = _roleRepository.Table
            .Where(r => r.Id == roleId && !r.IsDeleted)
            .SelectMany(r => r.Menus)
            .Any(m => m.Id == menuId);

        if (existingRelation)
        {
            return ApiResult.Fail(400, "角色已拥有该菜单权限");
        }

        var role = await _roleRepository.GetByIdAsync(roleId);
        if (role == null)
        {
            return ApiResult.Fail(404, "角色不存在");
        }
        if (role.IsDeleted)
        {
            return ApiResult.Fail(404, "角色已删除");
        }
        if (!role.IsActive)
        {
            return ApiResult.Fail(403, "角色已禁用");
        }

        var menuPermission = _menuRepository.Table.FirstOrDefault(m => m.Id == menuId);
        if (menuPermission == null)
        {
            return ApiResult.Fail(404, "菜单权限不存在");
        }
        if (menuPermission.IsDeleted)
        {
            return ApiResult.Fail(404, "菜单权限已删除");
        }
        if (!menuPermission.IsActive)
        {
            return ApiResult.Fail(403, "菜单权限已禁用");
        }

        // 赋予角色菜单权限
        role.Menus.Add(menuPermission);
        role.UpdatedAt = DateTime.UtcNow;        // 更新时间（系统自动设置，不可修改）
        role.UpdatedBy = Guid.Empty;             // 更新者ID（系统自动设置，不可修改）TODO: 应从当前用户上下文获取
        await _roleRepository.UpdateAsync(role);

        return ApiResult.Success(new { RoleId = role.Id, MenuId = menuId }, "菜单权限赋予成功");
    }

    /// <summary>
    /// 批量为角色分配菜单权限
    /// </summary>
    /// <param name="roleId">角色ID</param>
    /// <param name="assignMenusDto">批量分配菜单权限DTO</param>
    /// <returns>操作结果</returns>
    public async Task<dynamic> AssignMenusToRoleAsync(Guid roleId, AssignMenusToRoleDto assignMenusDto)
    {
        var role = await _roleRepository.GetByIdAsync(roleId);
        if (role == null)
        {
            return ApiResult.Fail(404, "角色不存在");
        }
        if (role.IsDeleted)
        {
            return ApiResult.Fail(404, "角色已删除");
        }
        if (!role.IsActive)
        {
            return ApiResult.Fail(403, "角色已禁用");
        }

        // 验证所有菜单ID是否有效
        var validMenuIds = _menuRepository.Table
            .Where(m => assignMenusDto.MenuIds.Contains(m.Id) && !m.IsDeleted && m.IsActive)
            .Select(m => m.Id)
            .ToList();

        if (validMenuIds.Count != assignMenusDto.MenuIds.Count)
        {
            var invalidMenuIds = assignMenusDto.MenuIds.Except(validMenuIds).ToList();
            return ApiResult.Fail(400, $"以下菜单ID无效或已禁用: {string.Join(", ", invalidMenuIds)}");
        }

        // 获取有效的菜单实体
        var menusToAssign = _menuRepository.Table
            .Where(m => validMenuIds.Contains(m.Id))
            .ToList();

        if (assignMenusDto.IsOverride)
        {
            // 覆盖模式：直接删除中间表中该角色的所有菜单权限记录，然后分配新权限

            // 使用原生SQL直接删除中间表记录，确保彻底清除
            await _dbContext.Database.ExecuteSqlRawAsync(
                "DELETE FROM role_menus WHERE role_id = {0}", roleId);

            // 重新获取角色实体以确保从数据库获取最新状态
            var updatedRole = await _roleRepository.GetByIdAsync(roleId);
            if (updatedRole == null)
            {
                return ApiResult.Fail(404, "角色删除权限后无法找到");
            }

            // 添加新的菜单权限
            foreach (var menu in menusToAssign)
            {
                updatedRole.Menus.Add(menu);
            }

            updatedRole.UpdatedAt = DateTime.UtcNow;
            updatedRole.UpdatedBy = Guid.Empty; // TODO: 应从当前用户上下文获取
            await _roleRepository.UpdateAsync(updatedRole);

            var overrideResult = new
            {
                RoleId = updatedRole.Id,
                AssignedMenuIds = validMenuIds,
                TotalAssigned = validMenuIds.Count,
                Mode = "覆盖",
                Message = "已直接清除数据库中间表的所有原有菜单权限并分配新权限"
            };

            return ApiResult.Success(overrideResult, "批量菜单权限分配成功（覆盖模式）");
        }
        else
        {
            // 追加模式：只添加角色还没有的菜单权限
            var existingMenuIds = role.Menus.Select(m => m.Id).ToHashSet();
            var newMenus = menusToAssign.Where(m => !existingMenuIds.Contains(m.Id)).ToList();

            if (newMenus.Count == 0)
            {
                return ApiResult.Fail(400, "角色已拥有所有指定的菜单权限");
            }

            foreach (var menu in newMenus)
            {
                role.Menus.Add(menu);
            }

            role.UpdatedAt = DateTime.UtcNow;
            role.UpdatedBy = Guid.Empty; // TODO: 应从当前用户上下文获取
            await _roleRepository.UpdateAsync(role);

            var appendResult = new
            {
                RoleId = role.Id,
                AssignedMenuIds = newMenus.Select(m => m.Id).ToList(),
                TotalAssigned = newMenus.Count,
                Mode = "追加"
            };

            return ApiResult.Success(appendResult, "批量菜单权限分配成功（追加模式）");
        }
    }

    /// <summary>
    /// 为角色一键分配所有菜单权限
    /// </summary>
    /// <param name="roleId">角色ID</param>
    /// <returns>操作结果</returns>
    public async Task<dynamic> AssignAllMenusToRoleAsync(Guid roleId)
    {
        var role = await _roleRepository.GetByIdAsync(roleId);
        if (role == null)
        {
            return ApiResult.Fail(404, "角色不存在");
        }
        if (role.IsDeleted)
        {
            return ApiResult.Fail(404, "角色已删除");
        }
        if (!role.IsActive)
        {
            return ApiResult.Fail(403, "角色已禁用");
        }

        // 获取所有有效的菜单
        var allActiveMenus = _menuRepository.Table
            .Where(m => !m.IsDeleted && m.IsActive)
            .ToList();

        if (allActiveMenus.Count == 0)
        {
            return ApiResult.Fail(400, "系统中没有可用的菜单");
        }

        // 使用原生SQL直接删除中间表记录，确保彻底清除现有权限
        await _dbContext.Database.ExecuteSqlRawAsync(
            "DELETE FROM role_menus WHERE role_id = {0}", roleId);

        // 重新获取角色实体以确保状态同步
        var updatedRole = await _roleRepository.GetByIdAsync(roleId);
        if (updatedRole == null)
        {
            return ApiResult.Fail(404, "角色删除权限后无法找到");
        }

        // 添加所有菜单权限
        foreach (var menu in allActiveMenus)
        {
            updatedRole.Menus.Add(menu);
        }

        updatedRole.UpdatedAt = DateTime.UtcNow;
        updatedRole.UpdatedBy = Guid.Empty; // TODO: 应从当前用户上下文获取
        await _roleRepository.UpdateAsync(updatedRole);

        var result = new
        {
            RoleId = updatedRole.Id,
            AssignedMenuIds = allActiveMenus.Select(m => m.Id).ToList(),
            TotalAssigned = allActiveMenus.Count,
            Mode = "一键分配所有权限",
            Message = "已直接清除数据库中间表的所有原有菜单权限并分配所有可用菜单权限"
        };

        return ApiResult.Success(result, $"成功为角色分配了所有 {allActiveMenus.Count} 个菜单权限");
    }

    /// <summary>
    /// 创建新角色
    /// </summary>
    public async Task<dynamic> CreateRoleAsync(CreateRoleDto createRoleDto)
    {
        // 检查角色名称是否已存在
        var existingRole = _roleRepository.Table.FirstOrDefault(r => r.Name == createRoleDto.RoleName && !r.IsDeleted);
        if (existingRole != null)
        {
            return ApiResult.Fail(400, "角色名称已存在");
        }
        if (string.IsNullOrWhiteSpace(createRoleDto.RoleName))
        {
            return ApiResult.Fail(400, "角色名称不能为空");
        }

        var role = new Role
        {
            Id = Guid.NewGuid(),
            Name = createRoleDto.RoleName,
            Description = createRoleDto.Description,
            Code = Guid.NewGuid().ToString("N")[..8], // 生成8位编码
            IsActive = true,
            IsDeleted = false,
            CreatedAt = DateTime.UtcNow,    // 创建时间（系统自动设置，不可修改）
            UpdatedAt = DateTime.UtcNow,    // 更新时间（系统自动设置，不可修改）
            CreatedBy = Guid.Empty,         // 创建者ID（系统自动设置，不可修改）TODO: 应从当前用户上下文获取
            UpdatedBy = Guid.Empty          // 更新者ID（系统自动设置，不可修改）TODO: 应从当前用户上下文获取
        };

        await _roleRepository.CreateAsync(role);

        return ApiResult.Success(role, "角色创建成功");
    }

    /// <summary>
    /// 删除角色（软删除）
    /// </summary>
    /// <param name="roleId">角色ID</param>
    /// <returns>操作结果</returns>
    public async Task<dynamic> DeleteRoleAsync(Guid roleId)
    {
        var role = await _roleRepository.GetByIdAsync(roleId);
        if (role == null || role.IsDeleted)
        {
            return ApiResult.Fail(404, "角色不存在");
        }

        // 软删除
        role.IsDeleted = true;
        role.IsActive = false;
        role.UpdatedAt = DateTime.UtcNow;        // 更新时间（系统自动设置，不可修改）
        role.UpdatedBy = Guid.Empty;             // 更新者ID（系统自动设置，不可修改）TODO: 应从当前用户上下文获取

        await _roleRepository.UpdateAsync(role);

        return ApiResult.Success(new { RoleId = role.Id }, "角色删除成功");
    }

    /// <summary>
    /// 禁用角色
    /// </summary>
    /// <param name="roleId">角色ID</param>
    /// <returns>操作结果</returns>
    public async Task<dynamic> DisableRoleAsync(Guid roleId)
    {
        var role = await _roleRepository.GetByIdAsync(roleId);
        if (role == null || role.IsDeleted)
        {
            return ApiResult.Fail(404, "角色不存在");
        }

        if (!role.IsActive)
        {
            return ApiResult.Fail(400, "角色已处于禁用状态");
        }

        role.IsActive = false;
        role.UpdatedAt = DateTime.UtcNow;        // 更新时间（系统自动设置，不可修改）
        role.UpdatedBy = Guid.Empty;             // 更新者ID（系统自动设置，不可修改）TODO: 应从当前用户上下文获取
        await _roleRepository.UpdateAsync(role);

        return ApiResult.Success(new { RoleId = role.Id }, "角色已禁用");
    }

    /// <summary>
    /// 启用角色
    /// </summary>
    /// <param name="roleId">角色ID</param>
    /// <returns>操作结果</returns>
    public async Task<dynamic> EnableRoleAsync(Guid roleId)
    {
        var role = await _roleRepository.GetByIdAsync(roleId);
        if (role == null || role.IsDeleted)
        {
            return ApiResult.Fail(404, "角色不存在");
        }

        if (role.IsActive)
        {
            return ApiResult.Fail(400, "角色已处于启用状态");
        }

        role.IsActive = true;
        role.UpdatedAt = DateTime.UtcNow;        // 更新时间（系统自动设置，不可修改）
        role.UpdatedBy = Guid.Empty;             // 更新者ID（系统自动设置，不可修改）TODO: 应从当前用户上下文获取
        await _roleRepository.UpdateAsync(role);

        return ApiResult.Success(new { RoleId = role.Id }, "角色已启用");
    }

    /// <summary>
    /// 获取所有未删除的角色列表
    /// </summary>
    /// <returns>角色DTO集合</returns>
    public async Task<dynamic> GetAllRolesAsync(PageRequestDto pageRequestDto)
    {
        // 构建查询条件：只查询未删除的角色
        var query = _roleRepository.Table.Where(r => !r.IsDeleted);

        // 添加搜索条件
        if (!string.IsNullOrWhiteSpace(pageRequestDto.SearchKeyword))
        {
            var keyword = pageRequestDto.SearchKeyword.Trim();
            query = query.Where(r => r.Name.Contains(keyword) ||
                                   (r.Description != null && r.Description.Contains(keyword)));
        }

        // 添加排序
        if (!string.IsNullOrWhiteSpace(pageRequestDto.SortField))
        {
            switch (pageRequestDto.SortField.ToLower())
            {
                case "name":
                case "rolename":
                    query = pageRequestDto.SortDirection?.ToLower() == "desc"
                        ? query.OrderByDescending(r => r.Name)
                        : query.OrderBy(r => r.Name);
                    break;
                case "createdat":
                    query = pageRequestDto.SortDirection?.ToLower() == "desc"
                        ? query.OrderByDescending(r => r.CreatedAt)
                        : query.OrderBy(r => r.CreatedAt);
                    break;
                case "updatedat":
                    query = pageRequestDto.SortDirection?.ToLower() == "desc"
                        ? query.OrderByDescending(r => r.UpdatedAt)
                        : query.OrderBy(r => r.UpdatedAt);
                    break;
                case "isactive":
                    query = pageRequestDto.SortDirection?.ToLower() == "desc"
                        ? query.OrderByDescending(r => r.IsActive)
                        : query.OrderBy(r => r.IsActive);
                    break;
                default:
                    query = query.OrderBy(r => r.CreatedAt); // 默认按创建时间排序
                    break;
            }
        }
        else
        {
            query = query.OrderBy(r => r.CreatedAt); // 默认按创建时间排序
        }

        // 获取总数
        var totalCount = await Task.FromResult(query.LongCount());

        // 执行分页查询
        var roles = await Task.FromResult(query
            .Skip((pageRequestDto.PageIndex - 1) * pageRequestDto.PageSize)
            .Take(pageRequestDto.PageSize)
            .Select(role => new RoleDto
            {
                Id = role.Id,
                RoleName = role.Name,
                Description = role.Description ?? string.Empty,
                IsActive = role.IsActive,        // 使用实际的激活状态
                IsDelete = role.IsDeleted,       // 使用实际的删除状态
                CreatedAt = role.CreatedAt,      // 使用实际的创建时间（不可修改）
                UpdatedAt = role.UpdatedAt,      // 使用实际的更新时间（不可修改）
                CreatedBy = role.CreatedBy,      // 使用实际的创建者ID（不可修改）
                UpdatedBy = role.UpdatedBy       // 使用实际的更新者ID（不可修改）
            })
            .ToList());

        // 计算分页信息
        var totalPages = (int)Math.Ceiling((double)totalCount / pageRequestDto.PageSize);

        return new
        {
            PageIndex = pageRequestDto.PageIndex,
            PageSize = pageRequestDto.PageSize,
            TotalCount = totalCount,
            TotalPages = totalPages,
            HasPreviousPage = pageRequestDto.PageIndex > 1,
            HasNextPage = pageRequestDto.PageIndex < totalPages,
            Data = roles,
            SearchKeyword = pageRequestDto.SearchKeyword,
            SortField = pageRequestDto.SortField,
            SortDirection = pageRequestDto.SortDirection
        };
    }

    /// <summary>
    /// 移除角色的菜单权限
    /// </summary>
    /// <param name="roleId">角色ID</param>
    /// <param name="menuId">菜单ID</param>
    /// <returns>操作结果</returns>
    public async Task<dynamic> RemoveMenuFromRoleAsync(Guid roleId, Guid menuId)
    {
        // 检查角色是否拥有该菜单权限 - 使用Table查询来检查关系
        var hasPermission = _roleRepository.Table
            .Where(r => r.Id == roleId && !r.IsDeleted)
            .SelectMany(r => r.Menus)
            .Any(m => m.Id == menuId);

        if (!hasPermission)
        {
            return ApiResult.Fail(400, "角色未拥有该菜单权限");
        }

        var role = await _roleRepository.GetByIdAsync(roleId);
        if (role == null || role.IsDeleted)
        {
            return ApiResult.Fail(404, "角色不存在");
        }
        if (!role.IsActive)
        {
            return ApiResult.Fail(400, "角色已禁用");
        }

        var menuPermission = _menuRepository.Table.FirstOrDefault(m => m.Id == menuId);
        if (menuPermission == null)
        {
            return ApiResult.Fail(404, "菜单不存在");
        }

        // 移除角色菜单权限
        role.Menus.Remove(menuPermission);
        role.UpdatedAt = DateTime.UtcNow;        // 更新时间（系统自动设置，不可修改）
        role.UpdatedBy = Guid.Empty;             // 更新者ID（系统自动设置，不可修改）TODO: 应从当前用户上下文获取
        await _roleRepository.UpdateAsync(role);

        return ApiResult.Success(new { RoleId = role.Id }, "菜单权限移除成功");
    }

    /// <summary>
    /// 更新角色信息
    /// </summary>
    /// <param name="roleId">角色ID</param>
    /// <param name="updateRoleDto">角色更新参数</param>
    /// <returns>操作结果</returns>
    public async Task<dynamic> UpdateRoleAsync(Guid roleId, UpdateRoleDto updateRoleDto)
    {
        var role = await _roleRepository.GetByIdAsync(roleId);
        if (role == null || role.IsDeleted)
        {
            return ApiResult.Fail(404, "角色不存在");
        }
        if (!role.IsActive)
        {
            return ApiResult.Fail(400, "角色已禁用");
        }

        // 检查角色名称是否与其他角色重复
        var existingRole = _roleRepository.Table.FirstOrDefault(r => r.Name == updateRoleDto.RoleName && r.Id != roleId && !r.IsDeleted);
        if (existingRole != null)
        {
            return ApiResult.Fail(400, "角色名称已存在");
        }

        role.Name = updateRoleDto.RoleName;
        role.Description = updateRoleDto.Description;
        role.IsActive = updateRoleDto.IsActive;
        role.UpdatedAt = DateTime.UtcNow;        // 更新时间（系统自动设置，不可修改）
        role.UpdatedBy = Guid.Empty;             // 更新者ID（系统自动设置，不可修改）TODO: 应从当前用户上下文获取
        // 注意：CreatedAt 和 CreatedBy 不允许修改
        await _roleRepository.UpdateAsync(role);

        return ApiResult.Success(role, "角色更新成功");
    }


    public async Task<dynamic> GetRoleByIdAsync(Guid roleId)
    {
        var role = await _roleRepository.GetByIdAsync(roleId);
        if (role == null || role.IsDeleted)
        {
            return ApiResult.Fail(404, "角色不存在");
        }
        if (role.IsActive == false)
        {
            return ApiResult.Fail(400, "角色已禁用");
        }


        return ApiResult.Success(new RoleDto
        {
            Id = role.Id,
            RoleName = role.Name,
            Description = role.Description ?? string.Empty,
            IsActive = role.IsActive,
            IsDelete = role.IsDeleted,
            CreatedAt = role.CreatedAt,
            UpdatedAt = role.UpdatedAt,
            CreatedBy = role.CreatedBy,
            UpdatedBy = role.UpdatedBy
        });
    }

    /// <summary>
    /// 获取角色的菜单权限
    /// </summary>
    /// <param name="roleId">角色ID</param>
    /// <returns>角色的菜单权限列表</returns>
    public async Task<dynamic> GetRoleMenusAsync(Guid roleId)
    {
        // 使用Table来包含菜单关联数据，而不是GetByIdAsync
        var role = await Task.FromResult(_roleRepository.Table
            .Where(r => r.Id == roleId && !r.IsDeleted)
            .Select(r => new
            {
                r.Id,
                r.Name,
                r.IsActive,
                r.IsDeleted,
                Menus = r.Menus.Where(m => !m.IsDeleted && m.IsActive).ToList()
            })
            .FirstOrDefault());

        if (role == null)
        {
            return ApiResult.Fail(404, "角色不存在");
        }

        // 获取角色的所有菜单权限
        var roleMenus = role.Menus
            .Select(menu => new MenuDto
            {
                Id = menu.Id,
                Name = menu.Name,
                Path = menu.Path,
                Icon = menu.Icon,
                ParentId = menu.ParentId,
                Sort = menu.Sort,
                Code = menu.Code,
                IsActive = menu.IsActive,
                IsDeleted = menu.IsDeleted,
                CreatedAt = menu.CreatedAt,
                UpdatedAt = menu.UpdatedAt,
                CreatedBy = menu.CreatedBy,
                UpdatedBy = menu.UpdatedBy
            })
            .OrderBy(m => m.Sort)
            .ThenBy(m => m.Name)
            .ToList();

        return ApiResult.Success(new
        {
            RoleId = role.Id,
            RoleName = role.Name,
            MenuCount = roleMenus.Count,
            Menus = roleMenus
        }, "获取角色菜单权限成功");
    }
}